package com.net.xpay.alipay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayRequest;
import com.alipay.api.AlipayResponse;
import com.alipay.api.domain.AlipayDataBillEreceiptApplyModel;
import com.alipay.api.domain.AlipayDataBillEreceiptQueryModel;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.net.xpay.alipay.exception.AlipayClientException;
import com.net.xpay.alipay.model.CreateAlipayOpenSpIsvSignauthModel;
import com.net.xpay.alipay.model.CreateOpenAgentModel;
import com.net.xpay.alipay.model.SignOpenAgentCommonModel;
import com.net.xpay.alipay.model.TransOrderModel;
import com.net.common.util.SerializationUtil;
import com.net.xpay.core.utils.GsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.Map;

@Slf4j
public class PoseidonAlipayClient {

    private boolean isDev = false;

    private AlipayClient alipayClient;

    private final int retryTimes;

    @Autowired
    private AlipayProperties alipayProperties;

    public PoseidonAlipayClient(AlipayClient alipayClient, int retryTimes) {
        this.alipayClient = alipayClient;
        this.retryTimes = retryTimes;
    }

    public PoseidonAlipayClient(AlipayClient alipayClient, int retryTimes, boolean isDev) {
        this.alipayClient = alipayClient;
        this.retryTimes = retryTimes;
        this.isDev = isDev;
    }

    private <T extends AlipayResponse> T autoRetryExecute(AlipayRequest<T> req) throws AlipayApiException {
        return execute(req);
    }

    public <T extends AlipayResponse> T execute(AlipayRequest<T> req)
            throws AlipayApiException {
        T alipayRsp = isDev ? alipayClient.execute(req) : alipayClient.certificateExecute(req);
        log.debug("execute alipayRsp={}", SerializationUtil.obj2String(alipayRsp));
        return alipayRsp;
    }

    private <T extends AlipayResponse> T pageExecute(AlipayRequest<T> req)
            throws AlipayClientException {
        T alipayRsp;
        try {
            alipayRsp = alipayClient.pageExecute(req, "get");
            log.debug("pageExecute alipayRsp={}", SerializationUtil.obj2String(alipayRsp));
        } catch (AlipayApiException e) {
            throw new AlipayClientException(e.getErrCode(), e.getErrMsg());
        }
        if (alipayRsp.isSuccess()) {
            return alipayRsp;
        }
        throw new AlipayClientException(alipayRsp.getCode(), alipayRsp.getMsg(), alipayRsp.getSubCode(), alipayRsp.getSubMsg());
    }

    public AlipayFundBatchCreateResponse alipayFundBatchCreate(String authToken, TransOrderModel transOrder) throws AlipayApiException {
        AlipayFundBatchCreateRequest request = new AlipayFundBatchCreateRequest();
        request.setBizContent(GsonUtil.getGson().toJson(transOrder));

        request.putOtherTextParam("app_auth_token", authToken);

        return autoRetryExecute(request);
    }

    public AlipayFundBatchDetailQueryResponse alipayFundBatchDetailQuery(String authToken, String outBatchNo, Long pageNum) throws AlipayApiException {
        AlipayFundBatchDetailQueryRequest request = new AlipayFundBatchDetailQueryRequest();

        Map<String, Object> params = new HashMap<>();
        params.put("out_batch_no", outBatchNo);
        params.put("product_code", "BATCH_PAY_V2");
        params.put("biz_scene", "MESSAGE_BATCH_PAY");
        params.put("page_num", pageNum);

        request.setBizContent(GsonUtil.getGson().toJson(params));

        request.putOtherTextParam("app_auth_token", authToken);

        return autoRetryExecute(request);
    }

    public String alipayOpenInviteOrderCreate(String isvBizId, String alipayLogonId) throws AlipayApiException {
        AlipayOpenInviteOrderCreateRequest request = new AlipayOpenInviteOrderCreateRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("isv_biz_id", isvBizId);
        params.put("isv_return_url", alipayProperties.getAlipayCallbackUrl());
        params.put("alipay_logon_id", alipayLogonId);
        request.setBizContent(GsonUtil.getGson().toJson(params));
        return pageExecute(request).getBody();
    }

    public String alipayOpenInviteOrderCreate(String isvBizId, String alipayLogonId, String returnUrl) throws AlipayApiException {
        AlipayOpenInviteOrderCreateRequest request = new AlipayOpenInviteOrderCreateRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("isv_biz_id", isvBizId);
        params.put("isv_return_url", returnUrl);
        params.put("alipay_logon_id", alipayLogonId);
        request.setBizContent(GsonUtil.getGson().toJson(params));
        return pageExecute(request).getBody();
    }

    public String alipayFundTransPagePay(String token, String orderId, String returnUrl) throws AlipayApiException {
        AlipayFundTransPagePayRequest request = new AlipayFundTransPagePayRequest();
        request.setReturnUrl(returnUrl);
        Map<String, Object> params = new HashMap<>();
        params.put("order_id", orderId);
        params.put("product_code", "BATCH_API_TO_ACC");
        params.put("biz_scene", "MESSAGE_BATCH_PAY");

        request.setBizContent(GsonUtil.getGson().toJson(params));

        request.putOtherTextParam("app_auth_token", token);

        return pageExecute(request).getBody();

    }

    public String alipayFundBatchAppPay(String token, String batchTransId, String returnUrl) {
        AlipayFundBatchAppPayRequest request = new AlipayFundBatchAppPayRequest();
        request.setReturnUrl(returnUrl);
        Map<String, Object> params = new HashMap<>();
        params.put("batch_trans_id", batchTransId);
        request.setBizContent(GsonUtil.getGson().toJson(params));

        request.putOtherTextParam("app_auth_token", token);
        return pageExecute(request).getBody();
    }

    public AlipayFundBatchCloseResponse alipayFundBatchClose(String token, String orderId) throws AlipayApiException {
        AlipayFundBatchCloseRequest request = new AlipayFundBatchCloseRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("batch_trans_id", orderId);
        params.put("product_code", "BATCH_API_TO_ACC");
        params.put("biz_scene", "MESSAGE_BATCH_PAY");

        request.setBizContent(GsonUtil.getGson().toJson(params));

        request.putOtherTextParam("app_auth_token", token);

        return autoRetryExecute(request);

    }

    //新签约方式 开启代签约事务
    public AlipayOpenAgentCreateResponse createAlipayOpenAgent(CreateOpenAgentModel model) throws AlipayApiException {
        AlipayOpenAgentCreateRequest request = new AlipayOpenAgentCreateRequest();
        request.setBizContent(GsonUtil.getGson().toJson(model));
        return execute(request);
    }

    //代签约通用产品接口
    public AlipayOpenAgentCommonSignResponse signAlipayOpenAgentCommon(SignOpenAgentCommonModel model) throws AlipayApiException {
        AlipayOpenAgentCommonSignRequest request = new AlipayOpenAgentCommonSignRequest();
        request.setBatchNo(model.getBatchNo());
        request.setMccCode(model.getMccCode());
        request.setProductCode(model.getProductCode());
        request.setAppName(model.getAppName());
        return execute(request);
    }

    //提交待签约事务
    public AlipayOpenAgentConfirmResponse confirmAlipayOpenAgent(String batchNo) throws AlipayApiException {
        AlipayOpenAgentConfirmRequest request = new AlipayOpenAgentConfirmRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("batch_no", batchNo);
        request.setBizContent(GsonUtil.getGson().toJson(params));
        return execute(request);
    }

    //创建签约授权一体化
    public AlipayOpenSpIsvSignauthCreateResponse createAlipayOpenSpIsvSignauth(CreateAlipayOpenSpIsvSignauthModel model) throws AlipayApiException {
        AlipayOpenSpIsvSignauthCreateRequest request = new AlipayOpenSpIsvSignauthCreateRequest();
        request.setBizContent(GsonUtil.getGson().toJson(model));

        return execute(request);
    }

    //查询签约授权一体化审核结果
    //签约授权一体化订单ID
    //可通过alipay.open.sp.isv.signauth.create 接口获取
    public AlipayOpenSpIsvSignauthQueryResponse queryAlipayOpenSpIsvSignauth(String orderId) throws AlipayApiException {
        AlipayOpenSpIsvSignauthQueryRequest request = new AlipayOpenSpIsvSignauthQueryRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("order_id", orderId);
        request.setBizContent(GsonUtil.getGson().toJson(params));
        return execute(request);
    }

    //下载电子回单
    //申请批次汇总回单，传入 batch_trans_id（批次单据号）在批次接口调用实时返回/在根据外部订单号查询返回。
    //申请批次明细回单，传入 detail_id （批次明细订单号），在 alipay.fund.batch.detail.query（批量转账明细查询接口）返回的明细订单id
    public AlipayDataBillEreceiptApplyResponse applyAlipayDataBillEreceipt(AlipayDataBillEreceiptApplyModel model, String token) throws AlipayApiException {
        AlipayDataBillEreceiptApplyRequest request = new AlipayDataBillEreceiptApplyRequest();
        model.setType("FUND_DETAIL");
        request.putOtherTextParam("app_auth_token", token);

        request.setBizModel(model);
        return execute(request);
    }

    //查询回单下载链接 返回的链接有效期30秒
    public AlipayDataBillEreceiptQueryResponse queryAlipayDataBillEreceipt(String fileId, String token) throws AlipayApiException {
        AlipayDataBillEreceiptQueryRequest request = new AlipayDataBillEreceiptQueryRequest();
        AlipayDataBillEreceiptQueryModel model = new AlipayDataBillEreceiptQueryModel();
        model.setFileId(fileId);
        request.setBizModel(model);
        request.putOtherTextParam("app_auth_token", token);
        return execute(request);
    }

}
